Full Stack Build Part 1 - Building and Deploying an API
#
What you will learn- Creating an API
- Setting Cors Headers
- Testing an API
- Deploying an API
#
SetupOpen up terminal in your django folder
activate your virtual environment
source ./djangoenv/bin/activate
generate a new django project
django-admin startproject todoproject
cd into the todoproject folder
test your dev server
python manage.py runserver
#
Creating the API- create a new app
django-admin startapp todos
#
DjangoRestFrameworkWhen creating an API previously we did without any external help and making basic crud routes ended being a bit tedious...
write all crud functions individually
we had to convert our data to json then back to a dictionary to send back as json
the shape of the data isn't we would traditionally would expect
we had to turn off CSRF security and other security features to make work
DjangoRestFramework fixes all the above and creates a nice abstraction for creating REST API's with django. Let's do it!
DJANGO REST FRAMEWORK DOCUMENTATION
install djangorestframework
pip install djangorestframework
install djangorestframework and the todos app in settings.py
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'todos.apps.TodosConfig', 'rest_framework']
#
Creating our Modeltodos/models.py
from django.db import models
class Todo(models.Model): subject = models.CharField(max_length=100) details = models.CharField(max_length=100)
#
Make and Run Migrationspython manage.py makemigrations
python manage.py migrate
#
Making Our SerializerSerializing objects into json strings and then turning them back into python dictionaries can be a tedious process. With djangorestframework, we can build a serializer for our model that handles all this for us along with arranging the data in a more traditional form.
- create a serializers.py in our todos app
from .models import Todofrom django.contrib.auth.models import User, Groupfrom rest_framework import serializers
# Our TodoSerializerclass TodoSerializer(serializers.HyperlinkedModelSerializer): class Meta: # The model it will serialize model = Todo # the fields that should be included in the serialized output fields = ['id', 'subject', 'details']
#
Creating Our Viewsetdjangorestframework has classes for building out views called ViewSets. With these we can wire up all our CRUD routes pretty easily.
in todos/views.py
from .models import Todofrom rest_framework import viewsetsfrom rest_framework import permissionsfrom .serializers import TodoSerializer
class TodoViewSet(viewsets.ModelViewSet): ## The Main Query for the index route queryset = Todo.objects.all() # The serializer class for serializing output serializer_class = TodoSerializer # optional permission class set permission level permission_classes = [permissions.AllowAny] #Coule be [permissions.IsAuthenticated]
#
Setting Up Our RouterTo make sure all of the ViewSets methods connects to the rights urls, djangorestframework provides with a router to wire it all up. Let's head over to our urls.py.
from django.contrib import adminfrom django.urls import path, includefrom rest_framework import routersfrom todos.views import TodoViewSet
# create a new routerrouter = routers.DefaultRouter()# register our viewsetsrouter.register(r'todos', TodoViewSet) #register "/todos" routes
urlpatterns = [ # add all of our router urls path('', include(router.urls)), path('admin/', admin.site.urls),]
#
Testing the APIfire up postman
create 3-4 todos with post requests to
/todos/
get the full list with a get request to
/todos/
see one todo with a get request to
/todos/<id>
edit a todo with a put request to
/todos/<id>
delete a todo with delete request to
/todos/<id>
#
Deploying the APINow it's time to deploy the API, so first we have setup to do...
install the libraries we need...
pip install django-heroku gunicorn django-cors-headers
gunicorn: web server to run in production
django-heroku: configures our app for heroku deployment
django-cors-headers: will be used to handle cors
If you have any issues with installing psychopg2 (django-heroku dep), it is either cause you don't have x-code installed on mac or on linux you need to install "libpq-dev", on ubuntu based systems the command would be
sudo apt-get install libpq-dev
#
setting up django-herokuIn settings.py
at the top import django-heroku
import django_heroku
at the bottom add
django_heroku.settings(locals())
#
setting up django-cors-headersIn settings.py
- install the django-cors-headers app
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'todos.apps.TodosConfig', 'rest_framework', 'corsheaders']
- add the cors middleware
MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'corsheaders.middleware.CorsMiddleware', ## <---- add here 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware',]
- after the middleware section add this line to allow all origins
CORS_ALLOW_ALL_ORIGINS = True ## <---- will allow all origins, read cors docs to limit
#
Additional Setup- create a file called
Procfile
in the root of your project (where manage.py is)
web: gunicorn todoproject.wsgi
- add a runtime.txt in the project root with your python version
python-3.9.0
- generate a list of dependencies in requirements.txt with the command
pip freeze > requirements.txt
make sure to redo this anytime you add new dependencies
#
Getting it to herokucreate a git repo in the root, commit, then push up to github.com repo
create a new heroku project, connect your git repo to it, deploy
run
python manage.py migrate
from the heroku dashboard or the heroku clitest you newly deployed api in postman.